using System;
using System.Web;
using System.Web.Routing;
using ManagedUIFlow.Infrastructure.Commands;
using ManagedUIFlow.Infrastructure.Flows;
using ManagedUIFlow.Infrastructure.Services;
using ManagedUIFlow.Model;
using Moq;
using Xunit;

namespace ManagedUIFlow.Specs.Infrastructure.Commands
{
    public class SubFlowSpecs
    {
        private readonly RequestContext _requestContext;
        private readonly SubFlow _subFlow;

        public SubFlowSpecs()
        {            
            var contextMock = new Mock<HttpContextBase>();
            _requestContext = new RequestContext(contextMock.Object, new RouteData());
            _subFlow = new SubFlow(_requestContext);
        }

        [Fact]
        public void StartSubFlow_SerializesParentFlowAndStartsNewFlow()
        {
            var flow = new ManagedFlow(Guid.NewGuid(), "foo", "bar", RedirectBehavior.Manual, "");
            var subFlowDef = new Flow("bar", "test", RedirectBehavior.Manual, "");
            var appControllerMock = new Mock<ApplicationController>();
            _subFlow.ApplicationController = appControllerMock.Object;
            var flowServiceMock = new Mock<FlowService>();
            _subFlow.FlowService = flowServiceMock.Object;
            var flowServiceBuilder = new FlowViewServiceBuilder();
            var serilizerMock = new Mock<IFlowViewService>();
            flowServiceMock.Setup(f => f.GetFlowDefinition(flow.CurrentNavigation)).Returns(subFlowDef);
            flowServiceBuilder.SetFlowViewService(serilizerMock.Object);
            _subFlow.FlowSerializerBuilder = flowServiceBuilder;

            _subFlow.Execute(flow);

            serilizerMock.Verify(f => f.Serialize(flow, _requestContext));
            appControllerMock.Verify(a => a.Execute(_requestContext, It.IsAny<ManagedFlow>()));            
        }

        [Fact]
        public void StartSubFlowWhichDoesNotExist_Throws()
        {
            var flow = new ManagedFlow(Guid.NewGuid(), "foo", "bar", RedirectBehavior.Manual, "");
            var appControllerMock = new Mock<ApplicationController>();
            var flowServiceMock = new Mock<FlowService>();
            var flowServiceBuilder = new FlowViewServiceBuilder();
            var serviceMock = new Mock<IFlowViewService>();            
            flowServiceBuilder.SetFlowViewService(serviceMock.Object);
            _subFlow.FlowSerializerBuilder = flowServiceBuilder;          
            _subFlow.ApplicationController = appControllerMock.Object;
            _subFlow.FlowService = flowServiceMock.Object;

            Assert.Throws<FlowException>(() => _subFlow.Execute(flow));

            flowServiceMock.Verify(f => f.GetFlowDefinition("bar"));
        }       
    }
}